use log::{debug, error};
use rusqlite::{params, ToSql};
use tauri::State;

use chrono::prelude::*;
use chrono::NaiveDateTime;

use crate::error::error::MyError;
use crate::model::db_connection::DatabaseConnection;
use crate::model::event::*;
use crate::model::output::Output;

#[tauri::command(rename_all = "snake_case")]
pub fn create_event(
    title: &str,
    content: &str,
    type_id: i32,
    end_time: &str,
    start_time: &str,
    state: State<DatabaseConnection>,
) -> Result<Output<Event>, MyError> {
    // debug!("event: {}", &event);
    // let event: Event = serde_json::from_str(event).map_err(|e| {
    //     error!("Parse JSON error when create event: {}", e);
    //     MyError::new(
    //         1000,
    //         "Parse JSON error when create event".to_string(),
    //         e.to_string(),
    //     )
    // })?;
    //
    debug!("start_time {}, end_time {}", start_time, end_time);

    let event = Event {
        id: 0,
        title: title.to_string(),
        content: content.to_string(),
        type_id,
        status: 0,
        start_time: NaiveDateTime::parse_from_str(start_time, "%Y-%m-%d %H:%M").unwrap(),
        end_time: NaiveDateTime::parse_from_str(end_time, "%Y-%m-%d %H:%M").unwrap(),
        created_by: "".to_string(),
        created_at: chrono::Utc::now().naive_utc(),
        modified_by: "".to_string(),
        modified_at: chrono::Utc::now().naive_utc(),
    };

    debug!("event {:?}", event);

    state
        .conn
        .lock()
        .unwrap()
        .execute(
            r#"INSERT INTO event (
        title, content, type_id, status, end_time, start_time,
        created_by, created_at, modified_by, modified_at)
        VALUES
        (
        ?,?,?,?,?,?,?,?,?,?
        )"#,
            params![
                event.title,
                event.content,
                event.type_id,
                event.status,
                event.end_time,
                event.start_time,
                event.created_by,
                event.created_at,
                event.modified_by,
                event.modified_at
            ],
        )
        .map_err(|e| {
            error!("Insert event error: {}", e);
            MyError::new(1002, "Insert event error".to_string(), e.to_string())
        })?;

    return Ok(Output::success("Ok".to_string(), None));
}

#[tauri::command(rename_all = "snake_case")]
pub fn update_event(
    id: i32,
    title: &str,
    content: &str,
    type_id: i32,
    status: i32,
    end_time: &str,
    start_time: &str,
    state: State<DatabaseConnection>,
) -> Result<Output<Event>, MyError> {
    // let event: Event = serde_json::from_str(data).map_err(|e| {
    //     error!("Parse JSON error when update event: {}", e);
    //     MyError::new(
    //         1000,
    //         "Parse JSON error when update event".to_string(),
    //         e.to_string(),
    //     )
    // })?;

    let event = Event {
        id,
        title: title.to_string(),
        content: content.to_string(),
        type_id,
        status,
        start_time: NaiveDateTime::parse_from_str(start_time, "%Y-%m-%d %H:%M").unwrap(),
        end_time: NaiveDateTime::parse_from_str(end_time, "%Y-%m-%d %H:%M").unwrap(),
        created_by: "admin".to_string(),
        created_at: chrono::Utc::now().naive_utc(),
        modified_by: "admin".to_string(),
        modified_at: chrono::Utc::now().naive_utc(),
    };

    let sql = r#"
        UPDATE event
        SET
            title = ?1,
            content = ?2,
            type_id = ?3,
            status = ?4,
            start_time=?5,
            end_time=?6,
            created_by = ?7,
            created_at = ?8,
            modified_by = ?9,
            modified_at = ?10
        WHERE id = ?11
    "#;

    let conn = state.conn.lock().unwrap();
    let affected_rows = conn
        .execute(
            sql,
            params![
                event.title,
                event.content,
                event.type_id,
                event.status,
                event.start_time,
                event.end_time,
                event.created_by,
                event.created_at,
                event.modified_by,
                event.modified_at,
                event.id,
            ],
        )
        .map_err(|e| MyError::database_error("Update event failed".to_string(), e.to_string()))?;

    if affected_rows == 0 {
        return Err(MyError::new(
            404,
            "event not found".to_string(),
            "".to_string(),
        ));
    }

    // 返回更新后的数据（可选）
    Ok(Output::success(
        "Update successful".to_string(),
        Some(event),
    ))
}

#[tauri::command(rename_all = "snake_case")]
pub fn list_event(
    start_time: String,
    end_time: String,
    state: State<'_, DatabaseConnection>,
) -> Result<Output<Vec<Event>>, MyError> {
    debug!("start_time： {:?}", start_time);
    debug!("end_time： {:?}", end_time);
    let (sql, params): (&str, Vec<&dyn ToSql>) = {
        (
            r#"SELECT id, title, content, type_id, status, start_time,end_time,
                    created_by, created_at, modified_by, modified_at
               FROM event where start_time >= ?1 and end_time < ?2"#,
            vec![&start_time, &end_time],
        )
    };

    let conn = state.conn.lock().unwrap();
    let mut stmt = conn.prepare(sql).map_err(|e| {
        MyError::database_error(
            "Prepare statement error in list_event".to_string(),
            e.to_string(),
        )
    })?;

    let rows = stmt
        .query_map(&*params, |row| {
            Ok(Event {
                id: row.get(0)?,
                title: row.get(1)?,
                content: row.get(2)?,
                type_id: row.get(3)?,
                status: row.get(4)?,
                start_time: row.get(5)?,
                end_time: row.get(6)?,
                created_by: row.get(7)?,
                created_at: row.get(8)?,
                modified_by: row.get(9)?,
                modified_at: row.get(10)?,
            })
        })
        .map_err(|e| {
            MyError::database_error(
                "Query mapping error in list_event".to_string(),
                e.to_string(),
            )
        })?;

    let mut event_list = Vec::new();
    for row in rows {
        let event = row.map_err(|e| {
            MyError::database_error("Row mapping error in list_event".to_string(), e.to_string())
        })?;
        event_list.push(event);
    }

    let day = NaiveDate::from_ymd_opt(2025, 9, 28)
        .unwrap()
        .and_hms_opt(12, 34, 56)
        .unwrap();

    Ok(Output::success("OK".to_string(), Some(event_list)))
}

#[tauri::command(rename_all = "snake_case")]
pub fn event_detail(
    event_id: i32,
    state: State<'_, DatabaseConnection>,
) -> Result<Output<Event>, MyError> {
    let conn = state.conn.lock().unwrap();

    let sql = "SELECT  id, title, content, type_id, status, start_time,end_time,
              created_by, created_at, modified_by, modified_at
       FROM event WHERE id = ?";

    let mut stmt = conn.prepare(sql).map_err(|e| {
        MyError::database_error(
            "Prepare statement error in event_detail".to_string(),
            e.to_string(),
        )
    })?;

    let row = stmt
        .query_row(params![event_id], |row| {
            Ok(Event {
                id: row.get(0)?,
                title: row.get(1)?,
                content: row.get(2)?,
                type_id: row.get(3)?,
                status: row.get(4)?,
                start_time: row.get(5)?,
                end_time: row.get(6)?,
                created_by: row.get(7)?,
                created_at: row.get(8)?,
                modified_by: row.get(9)?,
                modified_at: row.get(10)?,
            })
        })
        .map_err(|e| {
            MyError::database_error("Query row error in event_detail".to_string(), e.to_string())
        })?;

    //todo!("query contacts ");

    Ok(Output::success("OK".to_string(), Some(row)))
}
